﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Xml;
using System.Net;
using System.Windows.Forms;
using ilibrary.source.common;

namespace ilibrary.source.model.metasearch
{
    public class AmazonSearcher : IDBSearchEngine
    {
        private BackgroundWorker backWorker = new BackgroundWorker();
        private ISearchHandler cb;
        private List<DBResult> results = new List<DBResult>();

        private int pageNumber;
        private int totalResults;
        private int pageSize;

        public AmazonSearcher()
        {
            pageNumber = 1;
            totalResults = 1;
            pageSize = 10;
        }


        public void searchFor(string query, int page_number, ISearchHandler callBack)
        {
            cb = callBack;
            pageNumber = page_number;

            //create a new back worker
            backWorker.Dispose();
            backWorker = new BackgroundWorker();
            backWorker.DoWork += new DoWorkEventHandler(DoWork);
            backWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
            backWorker.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
            backWorker.WorkerReportsProgress = true;

            //run the search
            backWorker.RunWorkerAsync(query);
        }



        private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

            cb.searchDone(results, pageNumber, totalResults, pageSize);
        }

        private void DoWork(object sender, DoWorkEventArgs e)
        {

            doDBSearch((string)e.Argument);
        }

        private void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            cb.searchProgressChanged(e.ProgressPercentage);
        }


        private void doDBSearch(string query)
        {
            BackgroundWorker bw = backWorker;
            //load result from isbndb
            string title = query;


            results.Clear();


            try
            {

                ECSHelper helper = new ECSHelper("US");
                String sTmp = ""; //Power field

                foreach (string s in title.Split(Common.seps))
                {
                    if (s.Length > 0)
                        sTmp += s + "+";
                }
                //remove trailing +
                sTmp = sTmp.Substring(0, sTmp.Length - 1);

                helper.setProperty("Operation", "ItemSearch");
                helper.setProperty("SearchIndex", "Books");
                helper.setProperty("ResponseGroup", "Medium");
                helper.setProperty("ItemPage", "" + pageNumber);
                helper.setProperty("Keywords", sTmp);

                String url = helper.toString();

                WebClient client = new WebClient();

                XmlReader reader = XmlReader.Create(client.OpenRead(url));

                reader.MoveToContent();

                //get nb of results
                reader.ReadToFollowing("ItemPage");
                int page_number = int.Parse(reader.ReadString());

                reader.ReadToFollowing("TotalResults");
                int total_results = int.Parse(reader.ReadString());

                int page_size = 10; //amazon page size is always 10

                //disable more link if last set

                if (page_number * page_size >= total_results)
                    cb.enableNextLink(false);
                else cb.enableNextLink(true);
                if (page_number <= 1)
                    cb.enablePreviousLink(false);
                else cb.enablePreviousLink(true);


                totalResults = total_results;
                pageSize = page_size;
                pageNumber = page_number;

                while (reader.ReadToFollowing("Item"))
                {
                    DBResult res = new DBResult();
                    res.db = "AMAZON";


                    processBookData(reader.ReadSubtree(), res);
                    results.Add(res);
                    bw.ReportProgress(10); //10 is a dummy value. the progress will always be incremented by 10
                }
                reader.Close();
            }
            catch (Exception)
            {
                //results.Clear();
                MessageBox.Show("Unable to contact the remote web server.\r\nPlease, try again later.", "Connection Error");
                return;
            }
        }

        private void processBookData(XmlReader reader, DBResult res)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(reader);
            XmlNamespaceManager nms = new XmlNamespaceManager(doc.NameTable);
            nms.AddNamespace("bk", doc.DocumentElement.NamespaceURI);



            XmlNode node;
            node = doc.SelectSingleNode("//bk:ItemAttributes/bk:ISBN", nms);
            //isbn
            if (node != null)
                res.isbn = node.InnerXml;

            //image
            node = doc.SelectSingleNode("//bk:MediumImage/bk:URL", nms);
            if (node != null)
            {
                res.imageURL = node.InnerXml;
            }

            //authors
            res.authors = "";
            String tmp = "";
            foreach (XmlNode n in doc.SelectNodes("//bk:ItemAttributes/bk:Author", nms))
            {
                tmp += n.InnerXml + ";";
            }
            //while(reader.ReadToNextSibling(
            res.authors = tmp;

            //
            String binding = "", edition = "", pages = "";
            node = doc.SelectSingleNode("//bk:ItemAttributes/bk:Binding", nms);
            if (node != null)
                binding = node.InnerXml;
            node = doc.SelectSingleNode("//bk:Edition", nms);
            if (node != null)
                edition = "Edition: " + node.InnerXml;
            node = doc.SelectSingleNode("//bk:ItemAttributes/bk:NumberOfPages", nms);
            if (node != null)
                pages = node.InnerXml + " pages";
            processBookDetails(binding, edition, pages, res);

            res.publisher = "";
            node = doc.SelectSingleNode("//bk:ItemAttributes/bk:Publisher", nms);
            if (node != null)
                res.publisher = node.InnerXml;

            res.titleLong = "";
            res.title = "";
            node = doc.SelectSingleNode("//bk:ItemAttributes/bk:Title", nms);
            if (node != null)
            {
                res.title = node.InnerXml;
                res.titleLong = res.title;
            }


            //summary
            node = doc.SelectSingleNode("//bk:EditorialReview/bk:Content", nms);
            if (node != null)
            {
                res.summary = Common.expandTags(node.InnerXml);
            }


        }

        private void processBookDetails(String b, String e, String p, DBResult tmp)
        {
            String res = "";
            res += b + ";" + e + ";" + p;
            tmp.physical_description = res;
        }


    }
}
